/**380. O(1) 时间插入、删除和获取随机元素 */
function randomizedSet() {
    class RandomizedSet {
        #valToIndex: Record<number, number> = {}
        #valArr: number[] = []
        #log() {
            console.log('————当前valToIndex', this.#valToIndex);
        }
        insert(val: number): boolean {
            if (this.#valToIndex[val] !== undefined) return false
            this.#valToIndex[val] = this.#valArr.length
            this.#valArr.push(val)
            this.#log()
            return true
        }

        remove(val: number): boolean {
            if (this.#valToIndex[val] === undefined) return false
            const len = this.#valArr.length
            const index = this.#valToIndex[val]//要被删除的索引
            // 要被删除的 和 最后一个val 交换位置
            this.#valToIndex[this.#valArr[len - 1]] = index //把最后一位的索引换成被删除的索引
            this.#valArr[index] = this.#valArr[len - 1] //把最后一个val覆盖掉要被删除的val
            this.#valArr.pop()//弹出最后一个val
            delete this.#valToIndex[val]
            this.#log()
            return true
        }

        getRandom(): number {
            const randomIndex = Math.floor(Math.random() * this.#valArr.length)
            this.#log()
            return this.#valArr[randomIndex]
        }
    }
    //下面是测试代码
    const obj = new RandomizedSet()
    const funsKey: (keyof RandomizedSet)[] = ["insert", "insert", "remove", "insert", "remove", "getRandom"]
    const params = [[0], [1], [0], [2], [1], []]
    const res = []
    for (let i = 0; i < funsKey.length; i++) {
        console.log(funsKey[i], params[i][0]);
        const r = obj[funsKey[i]](params[i][0])
        res.push(r)
    }
    console.log('最终结果数组', res);
}
/**341. 扁平化嵌套列表迭代器
 * - 设计一个迭代器类，将传入的多维数组，增加一个迭代器。
 * - NestedIterator(List<NestedInteger> nestedList) 用嵌套列表 nestedList 初始化迭代器。
 * - int next() 返回嵌套列表的下一个整数。
 * - boolean hasNext() 如果仍然存在待迭代的整数，返回 true ；否则，返回 false 。
 */
function nestedIterator() {
    /**每个元素可以是 数字数组，也可以是数字 */
    type NestedInteger = NestedInteger[] | number
    class NestedIterator {
        /**装着 每一层数组 和 当前层遍历到的索引 的栈 */
        stack: { arr: NestedInteger[], index: number }[] = []

        constructor(nestedList: NestedInteger[]) {
            this.stack.push({
                arr: nestedList,
                index: 0
            })
        }

        hasNext(): boolean {
            const { stack } = this
            let top = stack[stack.length - 1]
            //在这里把边界外的索引丢掉
            while (top && top.index >= top.arr.length) {
                stack.pop()
                top = stack[stack.length - 1]
            }
            if (stack.length === 0) return false
            return true
        }

        next(): number {
            const { stack } = this
            const now = stack[stack.length - 1] //当前层  
            const nowElement = now.arr[now.index] //当前遍历的元素
            if (typeof nowElement === 'object' /* Array.isArray(nowElement) */) {//如果遍历到的元素是数组，就加一层 //力扣编辑器有毛病， Array.isArray(nowElement) 不生效
                now.index++//新层遍历完后，就会用到这个索引了
                stack.push({ arr: nowElement, index: 0 })
                return this.next()
            } else {
                now.index++
                return nowElement
            }
        }
    }
    // 下面是使用代码
    const obj = new NestedIterator([[1, 1], 2, [1, 1]])
    const a: number[] = []
    while (obj.hasNext()) {
        a.push(obj.next());
        console.log('正常调用，成功后a为', a);
    }
    return a
}